import { Directive, Input, HostListener, ElementRef, OnDestroy, OnInit } from '@angular/core';
import { Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { NgModel } from '@angular/forms';

@Directive({
  selector: '[nsDebounce][ngModel]'
})
export class DebounceDirective implements OnDestroy, OnInit {
  @Input('nsDebounce') debounceTime: number = 500;
  
  private valueSubject = new Subject<string>();
  private subscription!: Subscription;
  private originalEmit: any;

  constructor(private el: ElementRef, private ngModel: NgModel) {
    this.originalEmit = this.ngModel.update.emit;
    this.ngModel.update.emit = (value: any) => {
      if (value?.__fromDebounce) {
        this.originalEmit.call(this.ngModel.update, value.value);
      }
    };
  }

  ngOnInit() {
    this.subscription = this.valueSubject
      .pipe(
        distinctUntilChanged(),
        debounceTime(this.debounceTime),
      )
      .subscribe(value => {
        this.ngModel.viewToModelUpdate({ value, __fromDebounce: true });
      });
  }

  @HostListener('input', ['$event'])
  onInput(event: InputEvent) {
    const value = (event.target as HTMLInputElement).value;
    this.valueSubject.next(value);
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
    this.valueSubject.complete();
  }
}
